<사설> DB, JDBC, JPA, ... 내가 알아야 했던 것

#PoV

1. 이 포스트의 목적

어떤 개념들의 얼개를 잡고 싶은데, 개념과 개념이 어떤식으로 관계를 맺고있는지 파악하고 싶은데, 여기서 하는 말이 다르고 저기서 하는 말이 다르다. 그 상황에서 나는 어떻게 해야할까? 에 대해 고민하고 있는 사람들에게 도움이 되기를 바라면서 나의 경험과 방법을 얘기하고자 한다.


2. 마법같은 세상

개발을 하다보면 종종 사람들에게 감탄할 때가 있다. SOLID를 배운 대학생 때가 그랬고, 디자인 패턴이나 DDD를 이해했을 때가 그랬다. 생각해보면 대학교 1학년 때 과제의 정답이 재귀함수를 쓰는것임을 알고난 후 몇일동안 재귀함수가 이해 되지 않다가 이해했을 때, 씨언어의 포인터의 포인터의 포인터를 자연스럽게 사용하게 되었을 때 그 충격은 조금 더 컸던 것 같다. 이 맛에 개발을 하는 것도 꽤나 큰 것 같다. 다른 사람들이 제안한 멋진 사고의 산물을 경험하고 그 수혜를 누릴 수 있다는 것과, 나도 언젠가 사소한 것이라도 남길 수 있지 않을까 하는 기대감.

하지만 그 이면에는 개인적인 한계에 지속적으로 부딪친다는 어려움도 있다. 그리고 지금 내가 보고 있는 것들이 내가 이해하지 못한 무언가 있을거라는 두려움이 항상 뒤따른다. 강의를 들었어도 직접 파고들기 전까지는 마법처럼 보이는 것들이 많다. 클록에 따라 전자의 흐름을 제어한다는건 전류를 아날로그로 느끼고 있는 나로서는 마법같은 일이였고, 네트워킹의 여러 측면이 마법같은 일이였다.

거창한 말로 한계를 확장한다는 것은 이런 마법같은 일을 나의 현실로 데려온다는 말로 바꿀 수 있을 것 같다. 전자의 흐름은 아날로그 적이지만, 그것까지 고려해서 입력신호의 허용값을 설계한다. 예상처럼 온도에 따라 흐름의 특성이 바뀌어 오작동을 일으킬 확률이 높아지지만 그 확률을 낮추기 위해 여러 기술을 도입한다. 까지만 이해해도 주변 언저리에서 일어날 법한 일이 되는 것이다.

개발 공부를 한다는 것은 A는 A고 B는 B이다.를 배우는것은 아니라고 생각한다. 그것보다는 세상을 지각하는 방식을 생성하고 재구성하는 일 이라고 생각한다. (수전베리의 '내게 없는 감각'을 읽고나서는 더 그런 확신이 든다.) 그러기 위해서는 키가 큰 털뭉치도, 주둥이가 납짝한 털뭉치도 강아지로 볼 수 있어야 하고, 털뭉치 여러개 사이에서 이것이 고양이인지 강아지인지 구별도 할 수 있어야 한다. 자바를 사용하던 코틀린을 사용하던 공변성에 대한 개념을 가지고 적용할 수 있어야 하고 코틀린의 코루틴과 스레드는 구분해서 사용할 수 있어야 한다는 얘기로 말할 수 있지 않을까.


3. 내가 알고있는 DB, JDBC, JPA

디비는 데이터 저장소, JDBC는 자바에서 디비 조작을 편하게 하려고 만든것, JPA는 객체지향적으로 디비의 데이터를 사용하기 위해 만든것. 디비는 관계형과 비관계형이 있고, JDBC에는 HikariCP가 있고 JPA는 Hibernate가 있고, 데이터를 다룰 때 중요한 것은 ACID를 지키는 것,...

나머지는 검색을 해보면서 손을 더듬듯 찾아가면 된다. 이것을 바탕으로 실무를 하게되면 조금씩 더 알아가는 것들도 있고, 여러 상황을 마주하면서 습득하게 된 노하우들이 쌓여간다. 트랜잭션을 여기서부터 여기까지 걸면 되겠다. 트랜잭션 롤백과 락의 정책은 이렇게 하면 되겠다. 이렇게하면 영속성 컨텍스트가 달라지니까 저렇게 해야지. 하는 삶의 체험들. 이것으로 충분할까?

누군가는 트랜잭션 전파 방식의 특정 방식을 쓰면 커넥션이 하나 더 생긴다고 말하고, 누군가는 같은 쓰레드 내에서 트랜잭션만 새로 생성되는 거라고 한다. 커넥션마다 쓰레드가 다른가? 트랜잭션이 새로 생성된다는 말이 커넥션이 생성된다는 말인가? 쓰레드가 생성된다는 말인가?


4. 전체를 봐야 할 때가 온다.

내가 지금 JPA에 꽂혀있다면 JPA부터 시작해서 물리적 디비까지의 흐름으로 이해하게 될 수도 있고, 하이버네이트에 꽂혀있다면 추상체와 구현체의 흐름을 타고 물리적 디비까지 도달하게 될 수도 있다. 또 디비드라이버와 데이터소스에 꽂혀있다면 흐름은 역이 될수도 있고, 왼편이나 오른편이 될 수도 있다.

나의 시작은 @Transactional(propagation = Propagation.REQUIRES_NEW) 가 작동하지 않는다는 포스트를 본 것에서 시작했다. 그 전까지는 트랜잭션도 전파도 JPA도 이해하는것에 문제가 없다고 생각했다. 하지만, 그 포스트를 읽고 직접 테스트를 해보고 미심쩍은 부분들이 생기기 시작했다. 또 이것을 테스트하다보니 이것이 의도대로 작동하더라도 커넥션이나 쓰레드가 두개 생성되지 않았다. 뭘 믿어야 할지 알수가 없게 되었다. 이렇게는 안된다는 생각이 들었다. 전체를 포괄하는 어떤 것을 잡아야 한다고 생각했다.

많은 글들을 접하다 보면 이것이 한번에 쓱 정리되진 않는다. 헤매는 것은 어쩔 수 없다. 나중에는 어디서부터가 JPA고 어디까지가 JDBC인지 알 수 없어지는때도 오게됐는데, 이 때 한번 더 전략을 생각해보게 된다. 내가 가지고 있는 JPA의 개념은 뭔가? 이때까지만 해도 JPA는 JPA였다. 남들이 말하는 인터페이스, ORM을 위한 인터페이스였다. 내가 써야 하는 개념은 JDBC와 구분되는 JPA인데, JDBC도 인터페이스이고, 디비를 위한 것이다. 그럼 Datasource는 어디에 속하는거지?와 같은 의문이 생기게 된다.

이 때 나에게 도움이 됐던 건 큼직한 것들이 무엇인지 결정하고, 어떤 방향에서 보던 명확하게 전체 얼개를 잡아보는 것이였다. 포스트를 매우 많이 읽었기 때문에 요소들이 어떤게 있는지 대충은 구분지어졌다. 물리적 디비-JDBC, Datasource-ConnectionPool, 그것을 사용하는 SQL Mapper-JPA, JPA를 한번 더 덮는 Spring Data JPA 정도로 잡고 DriverManager, HikariCP, Hibernate등을 위치시킨다.


5. 세부를 봐야할 때가 같이 온다.

JPA는 나에게 그냥 인터페이스의 느낌은 아니였다. 인터페이스는 나에게 있어 달랑 한 페이지 짜리 종이같은 느낌이기 때문이다. 이 개념들이 정의된 이후의 JPA는 나에게 있어 '인터페이스 벌크'이다. 왠진 모르겠지만 나에게 인터페이스와 인터페이스 벌크는 느낌이 전혀 다르다. 이렇게 나의 생각을 표현하고나니 JPA가 내 주변의 일부가 되었다.

그 다음의 문제는 EntityManager, TransactionManager, TransactionCoordinator, Session같은 객체들이 쏟아져 나오면서 한번 더 정신을 차릴 수 없었다. 슬의생에서 나온 '개는 미키 미키가 여동생 여동생이 익순이 익순이는 개'와 같은 대사를 할 수 있는 상황이다.

이럴때는 얘와 쟤를 묶고 구분해야한다. 인터페이스인것끼리, 인터페이스의 구현체끼리, 우리가 다루는 것은 인터페이스 타입 객체이기 때문에 구현체보다 인터페이스를 보고 생각해야 할 때가 많을 수 있고, 실제 트랜잭션 발생이나 커넥션 객체로 조작할 때는 구현체의 코드를 봐야하고와 같은 전략을 생각하면서 묶고 풀고 구분해야한다.

그러나 이 모든건 전체 속에서 이루어져야한다. EntityManager를 따로 떨어뜨려서 persist를 하면 생기는 현상과, detach를 하면 생기는 현상을 이해하는 것은 전체로서 보게되었을 때 Connection객체에서 setAutoCommit과 만나면 이것이 무엇인가 싶어진다. 이런것들을 다 같이 이해하면 논리적 트랜잭션과 물리적 트랜잭션의 개념이 여기에 들어가면 된다는 것을 알게되면서 지식이 결합되고 분리된다.


6. 모든 블로그에 감사하자

이번에 이것들을 이해하기 위해서 수십개의 블로그를 들락거렸다. 부분적으로만 맞는 사실을 일반적인 것 처럼 적어놓은 블로그도, 아예 틀린 사실을 적어놓은 블로그도 있었다. 그 블로그들의 글을 테스트하고 다른 블로그의 글과 비교해서 무엇이 맞고 틀린지를 이해하는데에 시간을 매우 많이 할애했다.

결론을 내리고 나니 조금 화가 났다. 왜 돌려보지도 않고 올리는거지? 왜 제대로 이해하지 않고 쓰는거지? 라는 생각이 불쑥 들었다. 그런데 계속 정리하고 정리하다보니 생각이 조금 달라졌다. 내가 AOP라는 것을 개념으로만 알고 실제 사용 패턴을 숙지하고 있지 않았다면, 저 블로그의 글을 보며 맞다고 이해했을 것이였고, 한번 볼 때는 틀린것 같은 내용이였는데 두세번 보니 이런 면에서 보면 이 말도 맞는 말이다 싶은 글도 있었다. 그러니까 지금의 나의 시야에 따라서 그리고 관점에 따라서 모든 글이 멋진 글이거나 부족한 글이 되었다는 것이다.

모든 글을 이해하기 위해서, 맞고 틀림을 검증하기 위해서 더 심도있게 이해해야했다. 이젠 새로운 글을 봐도 이해가 편하고 어떤 부분을 보충해야하는지 알게되었다. 아직도 내가 잘못 이해한 글이 있을것이고 무엇보다 중요한 것은 내가 앞으로 쓰게 될 모든 글들은 누군가에겐 부족하거나 넘치는 글이 될 것이다. 내 글이 부족하게 느껴진다면 너그러운 양해와 가르침을 받을 수 있기를, 내 글이 넘치게 느껴진다면 나의 시야와 시각을 줄 수 있는 기회를 얻길 바라기로 했다.